package org.example.campusforum.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 *
 * 提供JWT令牌的生成、解析和验证功能。
 * 用于用户身份认证和授权，支持从令牌中提取用户信息。
 *
 * @author CampusForum Team
 * @version 1.0
 * @since 2024
 */
public class JwtUtils {

    /** JWT签名密钥 */
    private static final String SECRET = "your-256-bit-secret-1234567890abcdef";

    /** 加密密钥对象 */
    private static final SecretKey KEY = Keys.hmacShaKeyFor(SECRET.getBytes());

    /** 令牌过期时间（毫秒），24小时 */
    private static final long EXPIRATION_MS = 86400000;

    /**
     * 生成JWT令牌
     *
     * 根据用户ID和用户名生成包含用户信息的JWT令牌。
     * 令牌有效期为24小时。
     *
     * @param userId 用户ID
     * @param username 用户名（邮箱）
     * @return 生成的JWT令牌字符串
     */
    public static String generateToken(Long userId, String username) {
        // 创建载荷信息
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        claims.put("username", username);

        // 构建并返回JWT令牌
        return Jwts.builder()
                .setClaims(claims)                    // 设置载荷
                .setSubject(username)                 // 设置主题（用户名）
                .setIssuedAt(new Date())             // 设置签发时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_MS)) // 设置过期时间
                .signWith(KEY, SignatureAlgorithm.HS256) // 使用HS256算法签名
                .compact();
    }

    /**
     * 解析JWT令牌
     *
     * 验证并解析JWT令牌，返回载荷信息。
     *
     * @param token JWT令牌字符串
     * @return 解析后的Claims对象
     * @throws RuntimeException 当令牌无效时抛出异常
     */
    public static Claims parseToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(KEY)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 从JWT令牌中获取用户ID
     *
     * @param token JWT令牌字符串
     * @return 用户ID，解析失败时返回null
     */
    public static Long getUserId(String token) {
        try {
            Claims claims = parseToken(token);
            Object userIdObj = claims.get("userId");
            return userIdObj != null ? Long.valueOf(userIdObj.toString()) : null;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 从HTTP请求中提取JWT并解析出邮箱
     *
     * 从Authorization请求头中提取JWT令牌，并解析出用户邮箱（subject）。
     *
     * @param request HTTP请求对象
     * @return 用户邮箱
     * @throws RuntimeException 当令牌无效时抛出异常
     */
    public static String getEmailFromRequest(HttpServletRequest request) {
        // 从Authorization头获取Token（格式：Bearer <token>）
        String authHeader = request.getHeader("Authorization");
        String token = authHeader.substring(7); // 去掉"Bearer "前缀
        try {
            Claims claims = parseToken(token);
            return claims.getSubject();
        } catch (Exception e) {
            throw new RuntimeException("无效的Token: " + e.getMessage());
        }
    }
}
